package p.ithorns.sample.moudle2;

import org.springframework.lang.NonNull;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;

/**
 * ModulePathCondition
 *
 * @author ithorns
 * @version 1.0.0
 * @date 2021/10/26 15:40
 */
public class ModulePathCondition implements RequestCondition<ModulePathCondition> {

    private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    static {
        PATH_MATCHER.setCaseSensitive(false);
        PATH_MATCHER.setPathSeparator(ModuleConst.PATH_SYMBOL);
        PATH_MATCHER.setCachePatterns(true);
        PATH_MATCHER.setTrimTokens(true);
    }

    private final String path;

    public ModulePathCondition(String path) {
        this.path = complete(path);
    }

    private String complete(final String path) {
        if (StringUtils.hasText(path) && !path.startsWith(ModuleConst.PATH_SYMBOL)) {
            return ModuleConst.PATH_SYMBOL + path;
        }

        String completion;
        if (path.equals(ModuleConst.PATH_SYMBOL)) {
            completion = ModuleConst.ROOT_PATH;
        }else if (path.equals(ModuleConst.ERROR_PATH)) {
            completion = path;
        }  else if (!path.endsWith(ModuleConst.ANY_PATH)) {
            completion = path + ModuleConst.ROOT_PATH;
        } else {
            completion = path;
        }
        return completion;
    }

    @NonNull
    @Override
    public ModulePathCondition combine(ModulePathCondition other) {
        String combine = this.path;
        if (!this.path.equals(other.path) && PATH_MATCHER.matchStart(this.path, other.path)) {
            combine = PATH_MATCHER.combine(this.path, other.path);
        }
        return new ModulePathCondition(combine);
    }

    @Override
    public ModulePathCondition getMatchingCondition(HttpServletRequest request) {
        String uri = request.getRequestURI();
        return PATH_MATCHER.match(this.path, uri) ? this : null;
    }


    @Override
    public int compareTo(@NotNull ModulePathCondition other, @NotNull HttpServletRequest request) {
        if (null == this.path) {
            return -1;
        }
        if (null == other.path) {
            return 1;
        }
        return this.path.compareTo(other.path);
    }

}